package main

import (
	"context"
	"fmt"
	"github.com/360EntSecGroup-Skylar/excelize"
	"go.manyji.com/lib/log"
	"go.manyji.com/lib/util/convert"
	"reflect"
	"strings"
	"time"
)

func (a *data_DailyRechargeStatistics) Query(ctx context.Context, uid uint64, pp PaginationParam, queryConditions []string) interface{} {

	queryConditions = append(queryConditions, []string{
		"daily_recharge_statistics.deleted = 0",
		fmt.Sprintf("daily_recharge_statistics.leader_id = %v", uid),
	}...)

	var (
		condition = fmt.Sprintf(`
  LEFT JOIN user ON user.id = daily_recharge_statistics.account_id AND user.deleted = 0 AND user.role_id = %v
WHERE %v %v`, (&data_Role{}).GetChannelAgentRole().ID, strings.Join(queryConditions, " AND "), " GROUP BY date ORDER BY daily_recharge_statistics.create_at DESC")
		queryCountSQL = fmt.Sprintf(`
	SELECT 
	      COUNT(DISTINCT date)
	FROM
	    (
	    SELECT 
			daily_recharge_statistics.id,
			date as date,
			SUM(recharge_points_total) as recharge_points_total,
			SUM(bonus_points_total) as bonus_points_total,
			daily_recharge_statistics.leader_id as leader_id
		FROM daily_recharge_statistics
		%v) AS tmp
`, condition)
		querySQL = fmt.Sprintf(`
SELECT
    daily_recharge_statistics.id,
	date as date,
	SUM(recharge_points_total) as recharge_points_total,
	SUM(bonus_points_total) as bonus_points_total,
	daily_recharge_statistics.leader_id as leader_id
FROM daily_recharge_statistics
%v %v 
`, condition, fmt.Sprintf(" LIMIT %v OFFSET %v", pp.PageSize, (pp.PageIndex-1)*pp.PageSize))
	)

	log.Info("query sql ", querySQL)
	respCount, err := db.QueryRaw(ctx, queryCountSQL, QueryCount{})
	if err != nil {
		return err
	}

	if respCount == nil {
		return nil
	}

	count := respCount[0].(*QueryCount).Count

	respTaskList, err := db.QueryRaw(ctx, querySQL, DailyRechargeQueryResp{})
	if err != nil {
		return err
	}

	ret := map[string]interface{}{
		"list":  respTaskList,
		"total": count,
	}

	if ret != nil {

		var (
			rpt uint64
			bpt uint64
		)
		for _, v := range ret["list"].([]interface{}) {

			respDRs := v.(*DailyRechargeQueryResp)
			rpt += respDRs.RechargePointsTotal
			bpt += respDRs.BonusPointsTotal
		}

		ret["all"] = map[string]interface{}{
			"rpt": rpt,
			"bpt": bpt,
		}
	}

	return a.addQueryResponseSeq(pp, ret)
}

func (a *data_DailyRechargeStatistics) addQueryResponseSeq(p PaginationParam, req map[string]interface{}) interface{} {

	if req != nil {

		var enable bool
		if _, ok := req["total"]; ok {
			if _, ok := req["list"]; ok {
				enable = true
			}
		}
		if enable {
			var (
				indexStart = 1
				total      = req["total"].(uint64)
			)

			for i, _ := range req["list"].([]interface{}) {

				//resp := v.(*schemaCustomer.RechargeQueryRsp)
				seqNo := int(total) - (p.PageSize*(p.PageIndex-1) + (int(i) + 1)) + indexStart
				//seqNo := (p.PageSize*(p.PageIndex-1) + (int(i) + 1)) + autoIndexStart
				//req.(map[string]interface{})["list"].([]interface{})[i].(*schemaCustomer.UserQueryRsp).Seq = int64(seqNo)
				req["list"].([]interface{})[i].(*DailyRechargeQueryResp).SeqNo = int64(seqNo)
			}
		}
	}

	return req
}

func (a *data_DailyRechargeStatistics) Export(ctx context.Context, item map[string]interface{}) interface{} {

	var (
		seqs      = make(map[string]string)
		condition = fmt.Sprintf(`
WHERE daily_recharge_statistics.deleted = 0
AND daily_recharge_statistics.id IN (%v)
GROUP BY date
ORDER BY daily_recharge_statistics.create_at DESC`, strings.Join(strings.Split(item["ids"].(string), "|"), ","))
		querySQL = fmt.Sprintf(`
SELECT
  daily_recharge_statistics.id AS id,
  date AS date,
  SUM(recharge_points_total) AS recharge_points_total,
  SUM(bonus_points_total) AS bonus_points_total,
  leader_id AS leader_id,
  leader_name AS leader_name
FROM daily_recharge_statistics
%v
`, condition)
	)

	resp, err := db.QueryRaw(ctx, querySQL, DailyRechargeStatistics{})
	if err != nil {
		return err
	}

	selectedItems := []string{
		"id",
		"date",
		"recharge_points_total",
		"bonus_points_total",
	}

	for i, v := range strings.Split(item["ids"].(string), "|") {
		seqs[v] = strings.Split(item["seqs"].(string), "|")[i]
	}

	req := a.export(ctx, resp, 1, seqs, strings.Join(selectedItems, "|"))
	if req != nil {
		if _, ok := req.(error); ok {
			return req
		}
	}

	return req
}

func (a *data_DailyRechargeStatistics) export(ctx context.Context, req interface{}, funcTy int, seqs map[string]string, selectedItems string) interface{} {

	var (
		xlsx       = excelize.NewFile()
		categories = map[string]string{
			"A1": "序号",
			"B1": "充值日期",
			"C1": "充值总额",
			"D1": "赠送积分总额",
		}
		selectedItemMap = make(map[string]int)
		colWidths       = map[string]float64{"A": 8, "B": 22, "C": 18, "D": 12}
	)

	for key, value := range categories {
		xlsx.SetCellValue("Sheet1", key, value)
		_style, err := xlsx.NewStyle(`{"fill":{"type":"pattern","color":["#EEECE1"],"pattern":1},"alignment":{"horizontal":"center","vertical":"center"},"font":{"bold":true,"family":"宋体","size":10}}`)
		if err == nil {
			xlsx.SetCellStyle("Sheet1", key, key, _style)
		}
	}

	xlsx.SetRowHeight("Sheet1", 1, 20)

	for k, v := range colWidths {
		xlsx.SetColWidth("Sheet1", k, k, v)
	}

	for i, v := range strings.Split(fmt.Sprintf("%v", selectedItems), "|") {
		selectedItemMap[v] = i
	}

	p := map[string]struct{}{
		"recharge_points_total": {},
		"bonus_points_total":    {},
	}

	for index, vv := range req.([]interface{}) {

		var (
			columIndex  = 'A'
			columOffset = 1
		)

		for kkk, vvv := range Struct2Map(vv, "json") {

			if len(selectedItemMap) > 0 {
				if i, ok := selectedItemMap[kkk]; !ok {
					continue
				} else {
					columOffset = i
				}
			}

			cell := fmt.Sprintf("%c", int(columIndex)+columOffset) + convert.ToString(index+2)

			if reflect.TypeOf(vvv).Kind() == reflect.Ptr {
				vOf := reflect.ValueOf(vvv)
				if vOf.IsNil() {
					vvv = ""
				} else {
					vvv = vOf.Elem()
				}
			}

			if kkk == "id" {
				vvv = seqs[fmt.Sprintf("%v", vvv.(uint64))]
			}

			if _, ok := p[kkk]; ok {
				vvv = Decimal(float64(vvv.(uint64))/10000.0, 5)
			}

			xlsx.SetCellValue("Sheet1", cell, vvv)
		}

		xlsx.SetRowHeight("Sheet1", index+2, 18)
	}

	xlsx.SetSheetName("Sheet1", "第一页")

	filPath, fileName := a.getExportPath(convert.ToString(time.Now().UnixMilli())+".csv", 1)
	err := xlsx.SaveAs(filPath)
	if err != nil {
		return nil
	}

	req = fileName

	return req
}

func (a *data_DailyRechargeStatistics) getExportPath(fileName string, bizTy int) (string, string) {

	var (
		bizTyMap = map[int]string{
			1: "daily_recharge_statistics",
		}
	)

	relativePath := fmt.Sprintf("%v/export/%v", bizTyMap[bizTy], fileName)

	return GetFilePath(
		fmt.Sprintf("%v/%v",
			FileStorage,
			relativePath),
	), relativePath
}
